﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace KUMC.Neurology.SomatoTopo
{
    partial class FormAnalysis : Form
    {
        /*
         * Member
         * */
        private Subject[] m_Subjects = null;
        private Layer m_Template     = null;
        private Study m_Study        = null;

        private string[] m_SubjOpt = null;
        private string[] m_DistOpt = null;

        private Bitmap m_BmpResult = null;
        private int[] m_FiltMap = null;

        private string m_strSubFilt = null;
        private string m_strMapFilt = null;

        private bool m_bUpdateSubFilt = false;
        private bool m_bUpdateMapFilt = false;
        private bool m_bGo            = false;
        
        private const int TOOLBAR_WIDTH = 32;
        private const int PANEL_MARGIN  = 3;

        /*
         * Constructor
         * */
        public FormAnalysis()
        {
            InitializeComponent();
        }
        public FormAnalysis(Subject[] subjects, Layer template, string[] subjOpt, string[] distOpt, Study study)
            : this()
        {
            m_Subjects = subjects;
            m_Template = template;
            m_DistOpt = distOpt;
            m_SubjOpt = subjOpt;
            m_Study = study;

            for (int i = 0; i < subjOpt.Length; i++)
            {
                m_strSubFilt = "";
            }
        }

        /*
         * Event
         * */
        private void AnalysisForm_Load(object sender, EventArgs e)
        {
            Layout2Form();
        }
        private void AnalysisForm_Resize(object sender, EventArgs e)
        {
            Layout2Form();
        }
        private void pbResult_Paint(object sender, PaintEventArgs e)
        {   
            // Clear
            e.Graphics.Clear(Color.White);
            e.Graphics.DrawImage(m_Template.Bitmap, 0, 0);

            // Filter Condition
            Font font = new Font("Times New Roman", 12);

            

            //string strFiltCond = "N= " + m_Subjects.Length.ToString() + "\n" + m_strSubFilt + "\n\n" + m_strMapFilt;
            string strFiltCond = "N= " + m_Subjects.Length.ToString() + "\n\n" + m_strSubFilt;

            e.Graphics.DrawString(strFiltCond, font, Brushes.Black, 650, 10);


            // Scale Bar
            //Bitmap scalebar = Utility.GetScaleBar(Utility.GetRainbowColor());
            Bitmap scalebar = Utility.GetScaleBar(Utility.GetRedColor());
            e.Graphics.DrawImage(scalebar, 700, 550);
            e.Graphics.DrawString("%", font, Brushes.Black, 700, 650);

            if (m_bGo)
            {           
                e.Graphics.DrawImage(m_BmpResult, 0, 0);
            }

            e.Graphics.Save();
            
        }
        private void toolStripSubFilter_Click(object sender, EventArgs e)
        {
            FormSubFilt form = new FormSubFilt(m_SubjOpt);
            DialogResult result = form.ShowDialog();

            if (result == DialogResult.OK)
            {
                m_strSubFilt = null;
                m_Subjects = SubFilter(form.InputData);

                for (int i = 0; i < form.InputData.Length; i++)
                {
                    if (!form.InputData[i].Equals(""))
                    {
                        m_strSubFilt = m_strSubFilt + m_SubjOpt[i] + ": " + form.InputData[i] + "\n";
                    }

                }

                m_bUpdateSubFilt = true;
            }
            else if (result == DialogResult.No)
            {
                m_strSubFilt = "";
                m_Subjects = m_Study.GetSubjects();
            }
        }
        private void toolStripMapFilter_Click(object sender, EventArgs e)
        {
            FormMapFilt form = new FormMapFilt(m_DistOpt);
            DialogResult result = form.ShowDialog();

            if (result == DialogResult.OK)
            {
                int width         = m_Template.Bitmap.Width;
                int height        = m_Template.Bitmap.Height;
                Bitmap resultBmp  = new Bitmap(width, height);
                int filtIdx       = 0;

                for (int i = 0; i < m_DistOpt.Length; i++)
                {
                    if(m_DistOpt[i].Equals(form.LSide))
                    {
                        filtIdx = i;
                    }
                }

                m_FiltMap = MapFilter(filtIdx, form.Equation, int.Parse(form.RSide));
                m_strMapFilt = m_DistOpt[filtIdx] + "= " + form.RSide;
                m_bUpdateMapFilt = true;
            }
            else if (result == DialogResult.No)
            {
                m_strMapFilt = null;
                m_bUpdateMapFilt = false;
            }
        }
        private void toolStripGo_Click(object sender, EventArgs e)
        {
            int min = 0;
            int max = 0;

            if (!m_bUpdateMapFilt)
            {
                int width   = m_Template.Bitmap.Width;
                int height  = m_Template.Bitmap.Height;

                m_BmpResult = new Bitmap(width, height);
                m_FiltMap = MapFilter();
            }
            
            if (!toolStripTBScale.Text.Equals(""))
            {
                string[] strScale = toolStripTBScale.Text.Split(',');

                if (strScale.Count() == 2)
                {
                    min = int.Parse(strScale[0]);
                    max = int.Parse(strScale[1]);
                }
            }
            else
            {
                min = 0;
                max = m_FiltMap.Max();
            }

            Utility.Array2Bitmap(m_FiltMap, ref m_BmpResult, min, max);

            m_bUpdateMapFilt = false;
            m_bUpdateSubFilt = false;
            m_bGo = true;

            toolStripTBScale.Text = min.ToString() + ',' + max.ToString();

            pbResult.Invalidate();
        }
        private void toolStripToBMP_Click(object sender, EventArgs e)
        {
            SaveFileDialog sfd = new SaveFileDialog();
            sfd.InitialDirectory = @"C:\";
            sfd.Title = "Save To BMP";
            sfd.DefaultExt = "bmp";
            sfd.Filter = "Bitmap (*.bmp)|*.bmp";
            sfd.FilterIndex = 0;

            if (sfd.ShowDialog() == DialogResult.OK)
            {
                //m_BmpResult.Save(sfd.FileName, ImageFormat.Bmp, 
                //pbResult.Image.Save(sfd.FileName, ImageFormat.Bmp);
            }
            
        }

        /*
         * Methods
         * */
        private void Layout2Form()
        {
            Size pnSize = new Size(this.ClientSize.Width - (PANEL_MARGIN * 2), 
                                    this.ClientSize.Height - PANEL_MARGIN - TOOLBAR_WIDTH);
            this.pnPicturebox.Size = pnSize;
            this.pnPicturebox.Location = new Point(PANEL_MARGIN, PANEL_MARGIN);

            pbResult.Size = this.pnPicturebox.ClientSize;
        }
        private void Parser(string fullexp, out string op, out string rside1, out string rside2)
        {
            if (!fullexp.Equals(""))
            {
                string[] split = fullexp.Split(' ');

                if (split.Length == 1)
                {
                    // categorical value
                    op = "";
                    rside1 = split[0];
                    rside2 = "";
                }
                else if (split.Length == 2)
                {
                    // graded value
                    op = split[0];
                    rside1 = split[1];
                    rside2 = "";
                }
                else
                {
                    op = split[1];
                    rside1 = split[0];
                    rside2 = split[2];
                }
            }
            else
            {
                op = "";
                rside1 = "";
                rside2 = "";
            }
        }
        private int[] MapFilter()
        {
            int width = m_Template.Bitmap.Width;
            int height = m_Template.Bitmap.Height;
            int N = m_Subjects.Length;
            int[] result = new int[width * height];

            result.Initialize();

            for (int i = 0; i < width * height; i++)
            {
                for (int n = 0; n < N; n++)
                {
                    if (m_Subjects[n].Distribution[i] != 0)
                    {
                        result[i] += 100;
                    }
                    else
                    {
                        result[i] += 0;
                    }

                }
                if (N > 0)
                {
                    result[i] /= N;
                }
                else
                {
                    result[i] = 0;
                }
            }

            return result;
        }
        private int[] MapFilter(int index, string op, int rside)
        {
            int width = m_Template.Bitmap.Width;
            int height = m_Template.Bitmap.Height;
            int N = m_Subjects.Length;
            int[] result = new int[width * height];

            result.Initialize();
            
            for (int i = 0; i < width * height; i++)
            {
                for (int n = 0; n < N; n++)
                {
                    int decode = 0;

                    decode = Utility.Decoding(m_Subjects[n].Distribution[i], index);

                    switch (op)
                    {
                        case "=":
                            if (decode != rside) { decode = 0; }
                            break;

                        case "<":
                            if (decode >= rside) { decode = 0; }
                            break;

                        case ">":
                            if (decode <= rside) { decode = 0; }
                            break;

                        default:
                            break;
                    }

                    if (decode != 0)
                    {
                        result[i] += 100;
                    }
                    else
                    {
                        result[i] += decode;
                    }
                    
                }
                if (N > 0)
                {
                    result[i] /= N;
                }
                else
                {
                    result[i] = 0;
                }
            }

     
            return result;

        }
        private Subject[] SubFilter(string[] conditions)
        {
            List<Subject> list = new List<Subject>();
            Subject[] totsubjects = m_Study.GetSubjects();
            
            for(int i=0; i<totsubjects.Length; i++)
            {
                int j = 0;
                bool add = true;

                foreach (string condition in conditions)
                {
                    string op = null;
                    string rside1 = null;
                    string rside2 = null;
                    Parser(condition, out op, out rside1, out rside2);

                    if (add)
                    {
                        // categorical value
                        if (op.Equals(""))
                        {
                            if (!rside1.Equals(""))
                            {
                                if (totsubjects[i].Option[j] == null)
                                {
                                    add = false;
                                }
                                else if (!totsubjects[i].Option[j].ToUpper().Equals(rside1.ToUpper()))
                                {
                                   add = false;
                                }
                            }
                        }
                        else // graded value
                        {
                            if (totsubjects[i].Option[j] == null)
                            {
                                add = false;
                            }
                            else if (!totsubjects[i].Option[j].Equals("") && !totsubjects[i].Option[j].Equals("없음"))
                            {
                                switch (op)
                                {
                                    case "=":
                                        if (totsubjects[i].Option[j].Equals(rside1)) { }
                                        else { add = false; }
                                        break;

                                    case "<":
                                        if (double.Parse(totsubjects[i].Option[j]) < double.Parse(rside1)) { }
                                        else { add = false; }
                                        break;

                                    case ">":
                                        if (double.Parse(totsubjects[i].Option[j]) > double.Parse(rside1)) { }
                                        else { add = false; }
                                        break;

                                    case "<>":
                                        if (double.Parse(totsubjects[i].Option[j]) > double.Parse(rside1) &&
                                            double.Parse(totsubjects[i].Option[j]) < double.Parse(rside2)) { }
                                        else { add = false; }
                                        break;

                                    default:
                                        break;
                                }
                            }
                            else
                            {
                                add = false;
                            }
                        }
                        j++;
                    }
                    else
                    {
                        break;
                    }
                }




                if (add)
                {
                    list.Add(totsubjects[i]);
                }
            }

            return list.ToArray();
        }

    }
}
